﻿using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.IO;
using System.Linq;
using Autofac;
using Autofac.Integration.Web;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using NMock2;
using Vowei.Core;
using Vowei.Core.Models;
using Vowei.Web;
using Vowei.Data.Converters.Excel;
using Vowei.Data.Helpers;
using Vowei.Data.Models;
using Vowei.Data;
using Autofac.Integration.Web.Mvc;
using Vowei.Test.Library;
using System.Data.Entity.Infrastructure;

namespace vowei.test
{
    [TestClass]
    public class TestBase
    {
        protected IVoweiContext VoweiContext { get; private set; }

        static TestBase()
        {
            Database.DefaultConnectionFactory = new SqlConnectionFactory(@"Data Source=.\SQLEXPRESS;Integrated Security=SSPI;Database=TaskConnect");
            Database.SetInitializer(new VoweiContextTestInitializer());
            SetupIoc();
        }

        public TestBase()
        {
            Setting = new TestSetting()
            {
                DefaultFormUser = new Employee 
                {
                    Email = "yimin_shi@hotmail.com" 
                },
                DefaultWindowsUser = new Employee
                {
                    UserName = "vowei\\administrator"
                },
                DefaultUserName = "yimin_shi@hotmail.com"
            };

            VoweiContext = new VoweiContext(new VoweiContextImpl());
            Setting.DefaultResourceCalendar = (DbResourceCalendar)VoweiContext.ResourceCalendars.Find(Constants.BuiltIn.ResouceCalendar.StandardCalendarId);

        }

        private static void SetupIoc()
        {
            var builder = new ContainerBuilder();

            foreach (var type in typeof(G18nController).Assembly.GetTypes())
            {
                if (type.BaseType == typeof(G18nController))
                    builder.RegisterType(type);
            }
                        
            builder.Register(c => new Employee {
                Email = "yimin_shi@hotmail.com",
                UserName = "vowei\\administrator"
            }).As<IUser>();
            builder.RegisterType<VoweiContextImpl>();
            builder.RegisterType<VoweiContext>().AsImplementedInterfaces();
            builder.RegisterType<TestFakeTranslator>().AsImplementedInterfaces();

            IocContainer = builder.Build();
        }

        protected static IContainer IocContainer { get; private set; }

        private TestContext testContextInstance;

        public TestContext TestContext
        {
            get
            {
                return testContextInstance;
            }
            set
            {
                testContextInstance = value;
            }
        }

        [TestInitialize]
        public void Init()
        {
            MvcApplication.ContainerProviderStatic = new ContainerProvider(IocContainer);
        }

        [TestCleanup]
        public void Cleanup()
        {
            MvcApplication.ContainerProviderStatic = null;
        }

        public TestSetting Setting { get; private set; }

        protected void AreDateTimeEquals(DateTime? left, DateTime? right)
        {
            if (left.HasValue && right.HasValue)
            {
                Assert.AreEqual(left.Value.Year, right.Value.Year);
                Assert.AreEqual(left.Value.Month, right.Value.Month);
                Assert.AreEqual(left.Value.Day, right.Value.Day);
                Assert.AreEqual(left.Value.Hour, right.Value.Hour);
                Assert.AreEqual(left.Value.Minute, right.Value.Minute);
                Assert.AreEqual(left.Value.Second, right.Value.Second);
            }
            else
                Assert.AreEqual(left, right);
        }


        protected DbResourceCalendar CreateStandardResourceCalendar()
        {
            return Setting.DefaultResourceCalendar;
        }

        protected Project GetSvnProject(VoweiContextImpl context)
        {
            return context.Projects.Where(p => p.ScmType == Project.SupportedScm.Svn).First();
        }

        protected Project GetDefaultProject(VoweiContextImpl context)
        {
            return GetDefaultProject(new VoweiContext(context));
        }

        protected Project GetDefaultProject(IVoweiContext context)
        {
            var project = context.Projects.Find(VirtualContextInitializer.DefaultProjectId);
            if (project == null)
            {
                project = new Project
                {
                    Title = "Default Project",
                    ID = VirtualContextInitializer.DefaultProjectId,
                    Owner = Setting.DefaultFormUser.Email
                };
                var filename = Path.Combine(
                    TestContext.TestDeploymentDir, @"StatisticsHelpersTest_TopRequirementWorksBasicTest.xls");

                using (var stream = File.Open(filename, FileMode.Open, FileAccess.Read))
                {
                    var converter = new WorkItemExcelConverter(VoweiContext.TicketStatusManager);
                    var works = converter.ConvertFrom(stream);

                    context.Projects.Add(project);
                    context.SaveChanges();

                    ImportHelper.ImportDataTo(project, context, works, Setting.DefaultFormUser);
                    context.SaveChanges();
                }
            }

            return project;
        }
        
        protected Project GetDefaultUnModifiedProject(VoweiContextImpl context)
        {
            return context.Projects.Find(VirtualContextInitializer.UnchangedProjectId);
        }

        internal static Project CloneProjectHelper(Project project)
        {
            var clone = new Project()
            {
                ID = project.ID,
                Title = project.Title,
                StartDate = project.StartDate,
                DueDate = project.DueDate,
                OpenDate = project.OpenDate,
                ClosedDate = project.ClosedDate,
                Reporter = project.Reporter,
                Owner = project.Owner,
                ScmType = project.ScmType,
                ScmUrl = project.ScmUrl
            };

            foreach (var child in project.Children)
                clone.Children.Add(child);

            return clone;
        }

        internal static Requirement CloneRequirementHelper(Requirement requirement)
        {
            var ret = new Requirement()
            {
                ID = requirement.ID,
                Title = requirement.Title,
                Progress = requirement.Progress,
                AssignedTo = requirement.AssignedTo,
                BelongsToMilestone = requirement.BelongsToMilestone,
                BelongsToMilestoneId = requirement.BelongsToMilestoneId,
                ClosedDate = requirement.ClosedDate,
                Description = requirement.Description,
                LastModified = requirement.LastModified,
                LastModifiedBy = requirement.LastModifiedBy,
                OpenDate = requirement.OpenDate,
                BusinessValue = requirement.BusinessValue,
                Priority = requirement.Priority,
                Reporter = requirement.Reporter,
                Status = requirement.Status,
                TagText = requirement.TagText
            };

            foreach (var child in requirement.Children)
                ret.Children.Add(child);

            return ret;
        }

        internal static Milestone CreateMilestoneHelper(string testName)
        {
            return new Milestone()
            {
                Title = string.Format("{0}_Milestone", testName),
                StartDate = DateTime.Now,
                DueDate = DateTime.Now + TimeSpan.FromDays(30)
            };
        }

        internal static Project CreateProjectHelper(string testName)
        {
            return new Project()
            {
                Title = string.Format("{0}_Project", testName),
                Owner = Constants.BuiltIn.Users.Active,
                StartDate = DateTime.Now,
                DueDate = DateTime.Now + TimeSpan.FromDays(30)
            };
        }

        internal static Project CreateProjectHelper(string testName, IVoweiContext context)
        {
            var calendar = context.ResourceCalendars.Find(Constants.BuiltIn.ResouceCalendar.StandardCalendarId);
            return new Project()
            {
                Title = string.Format("{0}_Project", testName),
                Owner = Constants.BuiltIn.Users.Active,
                StartDate = DateTime.Now,
                DueDate = DateTime.Now + TimeSpan.FromDays(30),
                ProjectBaseCalendar = calendar
            };
        }
        
        internal static Task CreateTaskHelper(string testName, Milestone milestone)
        {
            return new Task()
            {
                Title = string.Format("{0}_Task", testName),
                AssignedTo = Constants.BuiltIn.Users.Active,
                StartDate = DateTime.Now < milestone.StartDate ? milestone.StartDate : DateTime.Now,
                DueDate = (DateTime.Now + TimeSpan.FromDays(1)) > milestone.DueDate ? milestone.DueDate : DateTime.Now + TimeSpan.FromDays(1),
                BelongsToMilestone = milestone
            };
        }

        internal static Requirement CreateRequirementHelper(string testName, Milestone milestone)
        {
            return new Requirement()
            {
                Title = string.Format("{0}_Requirement", testName),
                AssignedTo = Constants.BuiltIn.Users.Active,
                BusinessValue = 1234,
                BelongsToMilestone = milestone
            };
        }

        internal void ImportTestDataToProject(Project project, IVoweiContext context)
        {
            var filename = Path.Combine(
                TestContext.TestDeploymentDir, @"StatisticsHelpersTest_TopRequirementWorksBasicTest.xls");

            ImportTestDataToProject(project, context, filename);
        }

        internal void ImportTestDataToProject(Project project, IVoweiContext context, string excel)
        {
            using (var stream = File.Open(excel, FileMode.Open, FileAccess.Read))
            {
                var target = new WorkItemExcelConverter(VoweiContext.TicketStatusManager);
                var works = target.ConvertFrom(stream);
                ImportHelper.ImportDataTo(project, context, works, Setting.DefaultFormUser);
            }
        }

        protected IEnumerable<Comment> GetHistories(ITable item, VoweiContextImpl context)
        {
            return from h in context.Comments
                   where h.PostId.CompareTo(item.ID) == 0
                   orderby h.CommentDate descending
                   select h;
        }
    }

    public class TestSetting
    {
        public IUser DefaultFormUser { get; set; }

        public IUser DefaultWindowsUser { get; set; }

        public string DefaultUserName { get; set; }

        public DbResourceCalendar DefaultResourceCalendar { get; set; }

        public List<IUser> Team { get; private set; }

        private void DeleteDatabase()
        {
            var dbPath = @"E:\Workspace\vowei\src\vowei.test\bin\Debug\Vowei.Core.Models.VoweiContext.sdf";
            if (File.Exists(dbPath))
                File.Delete(dbPath);
        }

        private void CreateDatabase(VoweiContextImpl context)
        {
            try
            {
                context.Database.CreateIfNotExists();
            }
            catch
            {
            } 
        }
    }
}
